const express = require('express');
const multer = require('multer');
const mammoth = require('mammoth');
const TurndownService = require('turndown');
const path = require('path');
const fs = require('fs');
const { exec, spawn } = require('child_process');
const xlsx = require('xlsx');
const axios = require('axios');
require('dotenv').config(); // 加载.env环境变量
const logger = require('./logger'); // 引入日志模块
// 导入 DeepseekService
const DeepseekService = require('./deepseek_service'); 
// 导入 CCBFZ 服务
const CCBFZService = require('./ccbfz_service.js'); // 改为CommonJS导入方式

const app = express();
const upload = multer({ dest: 'uploads/' });
const turndownService = new TurndownService();
// 初始化 DeepseekService
const deepseekService = new DeepseekService();
// 初始化 CCBFZ 服务
const ccbfzService = new CCBFZService();

// 添加获取第一个可见工作表的辅助函数
function getFirstVisibleSheet(workbook) {
    if (!workbook || !workbook.SheetNames || workbook.SheetNames.length === 0) {
        throw new Error('无效的Excel工作簿或没有工作表');
    }
    
    // 首先尝试获取工作簿的Hidden属性信息
    const hidden = workbook.Workbook && workbook.Workbook.Sheets 
        ? workbook.Workbook.Sheets.map(s => s.Hidden) 
        : workbook.SheetNames.map(() => 0); // 如果没有Hidden属性，假设所有表都是可见的
    
    // 查找第一个未隐藏的工作表
    for (let i = 0; i < workbook.SheetNames.length; i++) {
        if (!hidden[i]) { // 0表示可见，1表示隐藏
            return workbook.SheetNames[i];
        }
    }
    
    // 如果所有表都隐藏了，则返回第一个工作表
    return workbook.SheetNames[0];
}

// 添加JSON解析中间件
app.use(express.json());

// 提供静态文件服务
app.use(express.static('static'));

// 添加对template目录的静态服务
app.use('/template', express.static(path.join(__dirname, 'template')));

// 添加Excel模板下载路由
app.get('/download-audit-template', (req, res) => {
    const templatePath = path.join(__dirname, 'template', 'DesignAuditTemple.xlsx');
    
    logger.info(`请求下载设计审核模板: DesignAuditTemple.xlsx`);
    
    if (!fs.existsSync(templatePath)) {
        logger.warn(`模板文件不存在: ${templatePath}`);
        return res.status(404).send('模板文件不存在');
    }
    
    try {
        logger.info(`开始下载设计审核模板: DesignAuditTemple.xlsx`);
        res.download(templatePath, 'DesignAuditTemple.xlsx', (err) => {
            if (err) {
                logger.error(`下载模板文件失败: ${err.message}`);
                return res.status(500).send('下载失败');
            }
        });
    } catch (error) {
        logger.error(`模板文件下载异常: ${error.message}`);
        res.status(500).send('服务器错误');
    }
});

app.get('/download-audit-template-with-prompt', (req, res) => {
    const templatePath = path.join(__dirname, 'template', 'DesignAuditTempleWithPrompt.xlsx');
    
    logger.info(`请求下载带prompt的设计审核模板: DesignAuditTempleWithPrompt.xlsx`);
    
    if (!fs.existsSync(templatePath)) {
        logger.warn(`模板文件不存在: ${templatePath}`);
        return res.status(404).send('模板文件不存在');
    }
    
    try {
        logger.info(`开始下载带prompt的设计审核模板: DesignAuditTempleWithPrompt.xlsx`);
        res.download(templatePath, 'DesignAuditTempleWithPrompt.xlsx', (err) => {
            if (err) {
                logger.error(`下载模板文件失败: ${err.message}`);
                return res.status(500).send('下载失败');
            }
        });
    } catch (error) {
        logger.error(`模板文件下载异常: ${error.message}`);
        res.status(500).send('服务器错误');
    }
});

// 请求日志中间件
app.use((req, res, next) => {
    logger.info(`${req.method} ${req.url} ${req.ip}`);
    next();
});

// 处理文件上传
app.post('/upload', upload.single('file'), async (req, res) => {
    if (!req.file) {
        logger.warn('没有文件上传');
        return res.status(400).json({ error: '没有文件上传' });
    }

    try {
        // 解码文件名，避免中文乱码
        const decodeFileName = (fileName) => {
            try {
                return Buffer.from(fileName, 'latin1').toString('utf8');
            } catch (e) {
                return fileName;
            }
        };
        
        const originalFileName = decodeFileName(req.file.originalname);
        const fileExtension = path.extname(originalFileName).toLowerCase();
        logger.info(`文件上传: ${originalFileName}，类型: ${fileExtension}`);
        
        if (fileExtension === '.docx') {
            // 处理Word文档
            logger.info(`开始处理Word文档: ${originalFileName}`);
            // 转换Word文档为HTML
            const result = await mammoth.convertToHtml({ path: req.file.path });
            const html = result.value;
            
            // 转换HTML为Markdown
            const markdown = turndownService.turndown(html);

            // 保存Markdown内容到临时文件，使用英文文件名避免乱码
            const timestamp = new Date().getTime();
            const mdFilename = `markdown_${timestamp}.md`;
            const mdPath = path.join('uploads', mdFilename);
            fs.writeFileSync(mdPath, markdown);

            // 删除上传的临时文件
            fs.unlinkSync(req.file.path);
            logger.info(`Word文档处理完成: ${originalFileName}`);

            // 返回转换后的HTML和Markdown文件信息
            res.json({ 
                success: true,
                content: html,
                markdown: {
                    filename: mdFilename,
                    path: '/download/' + mdFilename
                }
            });
        } else if (fileExtension === '.xlsx') {
            // 处理Excel文件，只保存并返回文件名供后续处理
            logger.info(`Excel文件已上传: ${originalFileName}`);
            res.json({
                success: true,
                message: '已上传Excel文件',
                filename: originalFileName,
                tempPath: req.file.path
            });
        } else {
            // 不支持的文件类型
            logger.warn(`不支持的文件类型: ${fileExtension}`);
            fs.unlinkSync(req.file.path);  // 删除临时文件
            return res.status(400).json({ error: '不支持的文件类型，仅支持.docx和.xlsx文件' });
        }
    } catch (error) {
        // 确保清理临时文件
        logger.error(`文件处理异常: ${error.message}`);
        if (req.file && fs.existsSync(req.file.path)) {
            fs.unlinkSync(req.file.path);
        }
        res.status(500).json({ error: '文件转换失败：' + error.message });
    }
});

// 全局存储审核任务进度的对象
const reviewTaskProgress = {};

// 为任务添加日志
function addTaskLog(taskId, logLevel, message) {
    if (reviewTaskProgress[taskId]) {
        // 确保logs数组存在
        if (!reviewTaskProgress[taskId].logs) {
            reviewTaskProgress[taskId].logs = [];
        }
        
        // 添加带时间戳的日志
        const timestamp = new Date().toLocaleTimeString();
        const logEntry = `[${timestamp}] [${logLevel.toUpperCase()}] ${message}`;
        
        // 记录日志
        reviewTaskProgress[taskId].logs.push(logEntry);
        
        // 限制日志数量，避免内存占用过大
        if (reviewTaskProgress[taskId].logs.length > 100) {
            // 只保留最近的100条日志
            reviewTaskProgress[taskId].logs = reviewTaskProgress[taskId].logs.slice(-100);
        }
        
        // 同时记录到服务器日志，确保日志级别存在
        try {
            const validLogLevels = ['info', 'warn', 'error', 'debug', 'success'];
            const normalizedLevel = logLevel.toLowerCase();
            // 如果日志级别不存在，默认使用info
            const level = validLogLevels.includes(normalizedLevel) ? normalizedLevel : 'info';
            // success级别logger中不存在，映射为info
            const loggerLevel = level === 'success' ? 'info' : level;
            logger[loggerLevel](`任务 ${taskId}: ${message}`);
        } catch (error) {
            console.error(`记录日志失败: ${error.message}`);
            logger.error(`记录日志失败: ${error.message}`);
        }
    }
}

// 获取审核任务进度
app.get('/review-progress/:taskId', (req, res) => {
    const { taskId } = req.params;
    const taskStatus = reviewTaskProgress[taskId];
    logger.info(`获取审核任务进度: ${taskId}, 状态: ${taskStatus ? taskStatus.status : '未找到'}`);
    
    if (!taskStatus) {
        logger.warn(`未找到审核任务: ${taskId}`);
        return res.status(404).json({ error: '未找到任务' });
    }
    
    res.json(taskStatus);
});

// 处理文档审核检查
app.post('/process-review', upload.fields([
    { name: 'wordFile', maxCount: 1 },
    { name: 'excelFile', maxCount: 1 }
]), async (req, res) => {
    try {
        const modelType = req.body.modelType || 'deepseek-reasoner';
        const wordFile = req.files?.wordFile?.[0];
        const excelFile = req.files?.excelFile?.[0];
        
        logger.info(`收到文档审核请求: 模型类型=${modelType}`);

        if (!wordFile || !excelFile) {
            logger.warn('文档审核请求缺少必要文件');
            return res.status(400).json({ error: '请同时提供Word文档和Excel文件' });
        }
        
        // 解决中文文件名显示问题，使用Buffer转换避免乱码
        const decodeFileName = (fileName) => {
            try {
                // 尝试解码文件名
                return Buffer.from(fileName, 'latin1').toString('utf8');
            } catch (e) {
                return fileName; // 如果解码失败，返回原始文件名
            }
        };
        
        const wordFileName = decodeFileName(wordFile.originalname);
        const excelFileName = decodeFileName(excelFile.originalname);
        
        logger.info(`文档审核文件: Word=${wordFileName}, Excel=${excelFileName}`);

        // 创建任务ID
        const taskId = Date.now().toString();
        logger.info(`创建审核任务: ${taskId}`);
        
        try {
            // 1. 先处理Word文档，转为MD文本
            logger.info(`开始处理Word文档: ${wordFileName}`);
            // 初始化任务进度和日志
            reviewTaskProgress[taskId] = {
                status: 'processing',
                total: 0,
                completed: 0,
                results: [],
                logs: []
            };
            
            addTaskLog(taskId, 'info', `开始处理Word文档: ${wordFileName}`);
            const wordResult = await mammoth.convertToHtml({ path: wordFile.path });
            const wordContent = wordResult.value;
            addTaskLog(taskId, 'info', `Word文档处理完成，内容长度: ${wordContent.length}`);
            
            // 2. 处理Excel文件，获取prompt列
            addTaskLog(taskId, 'info', `开始处理Excel文件: ${excelFileName}`);
            const workbook = xlsx.readFile(excelFile.path);
            // 获取第一个未隐藏的工作表
            const sheetName = getFirstVisibleSheet(workbook);
            const worksheet = workbook.Sheets[sheetName];
            const data = xlsx.utils.sheet_to_json(worksheet);
            
            if (data.length === 0) {
                addTaskLog(taskId, 'error', 'Excel文件中未找到有效数据');
                return res.status(400).json({ error: 'Excel文件中未找到有效数据' });
            }
            
            addTaskLog(taskId, 'info', `从Excel中读取到 ${data.length} 行数据`);
            
            // 更新任务总数
            reviewTaskProgress[taskId].total = data.length;
            
            // 3. 先返回任务ID，让前端开始轮询
            res.json({ taskId: taskId });
            
            // 4. 后台处理审核任务
            addTaskLog(taskId, 'info', `开始执行审核任务，使用模型: ${modelType}`);
            
            // 为每行数据调用审核API
            for (let i = 0; i < data.length; i++) {
                try {
                    const row = data[i];
                    const prompt = row.prompt || row.Prompt || `请审核第${i+1}行内容`;
                    
                    addTaskLog(taskId, 'info', `开始处理第 ${i+1}/${data.length} 行，使用模型: ${modelType}`);
                    
                    // 根据选择的模型调用不同的API
                    let apiResult;
                    
                    // 根据modelType判断使用哪个服务
                    if (modelType === 'deepseek-reasoner') {
                        // 使用公网Deepseek R1
                        addTaskLog(taskId, 'info', `调用公网Deepseek R1模型，处理第 ${i+1} 行...`);
                        apiResult = await deepseekService.reviewDocument(wordContent, prompt, modelType);
                        addTaskLog(taskId, 'success', `公网Deepseek R1模型返回成功，结果长度: ${(apiResult.result || '').length}`);
                        
                        // 添加模型响应文本摘要
                        const resultContent = apiResult.result || '';
                        if (resultContent.length > 0) {
                            // 截取前200个字符作为摘要
                            const previewText = resultContent.substring(0, 200) + (resultContent.length > 200 ? '...' : '');
                            addTaskLog(taskId, 'info', `模型响应摘要: "${previewText}"`);
                        }
                        
                        // 添加思考过程摘要(如果有)
                        if (apiResult.thinking && apiResult.thinking.length > 0) {
                            const thinkingPreview = apiResult.thinking.substring(0, 100) + (apiResult.thinking.length > 100 ? '...' : '');
                            addTaskLog(taskId, 'info', `思考过程摘要: "${thinkingPreview}"`);
                        }
                    } else {
                        // 使用建行方舟模型（满血版或蒸馏版）
                        addTaskLog(taskId, 'info', `调用建行方舟模型: ${modelType}，处理第 ${i+1} 行...`);
                        apiResult = await ccbfzService.reviewDocument(wordContent, prompt, modelType);
                        addTaskLog(taskId, 'success', `建行方舟模型返回成功，结果长度: ${(apiResult.result || '').length}`);
                        
                        // 添加模型响应文本摘要
                        const resultContent = apiResult.result || '';
                        if (resultContent.length > 0) {
                            // 截取前200个字符作为摘要
                            const previewText = resultContent.substring(0, 200) + (resultContent.length > 200 ? '...' : '');
                            addTaskLog(taskId, 'info', `模型响应摘要: "${previewText}"`);
                        }
                        
                        // 添加思考过程摘要(如果有)
                        if (apiResult.thinking && apiResult.thinking.length > 0) {
                            const thinkingPreview = apiResult.thinking.substring(0, 100) + (apiResult.thinking.length > 100 ? '...' : '');
                            addTaskLog(taskId, 'info', `思考过程摘要: "${thinkingPreview}"`);
                        }
                    }
                    
                    // 保存结果并更新进度
                    data[i].result = apiResult.answer || apiResult.result;
                    data[i].thinking = apiResult.thinking;
                    reviewTaskProgress[taskId].completed++;
                    reviewTaskProgress[taskId].results.push({
                        prompt: prompt,
                        result: apiResult.answer || apiResult.result,
                        thinking: apiResult.thinking
                    });
                    
                    addTaskLog(taskId, 'info', `第 ${i+1} 行处理完成，进度: ${reviewTaskProgress[taskId].completed}/${reviewTaskProgress[taskId].total}`);
                    
                } catch (rowError) {
                    addTaskLog(taskId, 'error', `处理第 ${i+1} 行时出错: ${rowError.message}`);
                    // 即使单行处理出错，也继续处理其他行
                    data[i].result = `处理错误: ${rowError.message}`;
                    data[i].thinking = '处理过程中出现错误';
                    reviewTaskProgress[taskId].completed++;
                }
            }
            
            // 5. 处理完成后，生成结果文件
            addTaskLog(taskId, 'info', '所有审核项处理完成，正在生成结果文件...');
            
            // 创建新的工作表
            const newWorkbook = xlsx.utils.book_new();
            const newWorksheet = xlsx.utils.json_to_sheet(data);
            xlsx.utils.book_append_sheet(newWorkbook, newWorksheet, sheetName);
            
            // 保存到新文件 - 使用英文名称避免乱码问题，但保留原始中文文件名信息
            const timestamp = Date.now();
            // 从原文件名中提取基本名称（不含扩展名），避免使用特殊字符
            const safeWordFileName = wordFileName.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_').substring(0, 30);
            const outputFilename = `audit_results_${safeWordFileName}_${timestamp}.xlsx`;
            const outputPath = path.join('uploads', outputFilename);
            xlsx.writeFile(newWorkbook, outputPath);
            
            // 更新任务状态
            reviewTaskProgress[taskId].status = 'completed';
            reviewTaskProgress[taskId].message = `审核完成，共处理 ${data.length} 个检查项`;
            reviewTaskProgress[taskId].downloadPath = '/download-excel/' + outputFilename;
            
            addTaskLog(taskId, 'success', `审核任务完成，结果文件已生成: ${outputFilename}`);
            
        } catch (error) {
            logger.error(`审核任务执行失败: ${error.message}`);
            logger.error(error.stack);
            
            if (reviewTaskProgress[taskId]) {
                addTaskLog(taskId, 'error', `审核任务执行失败: ${error.message}`);
                // 更新任务状态为失败
                reviewTaskProgress[taskId].status = 'failed';
                reviewTaskProgress[taskId].error = error.message;
            }
            
            // 由于响应已经发送，这里不再返回错误信息
        } finally {
            // 清理临时文件
            if (wordFile && fs.existsSync(wordFile.path)) {
                fs.unlinkSync(wordFile.path);
                addTaskLog(taskId, 'info', '清理临时Word文件');
            }
            if (excelFile && fs.existsSync(excelFile.path)) {
                fs.unlinkSync(excelFile.path);
                addTaskLog(taskId, 'info', '清理临时Excel文件');
            }
        }
    } catch (error) {
        logger.error(`处理审核请求失败: ${error.message}`);
        res.status(500).json({ error: '处理审核请求失败: ' + error.message });
    }
});

// 调用大模型API的函数
async function callModelAPI(modelType, prompt, content) {
    try {
        // 检查是否为Deepseek模型ID
        if (modelType === 'deepseek-reasoner') {
            logger.info('使用公网Deepseek模型API进行审核');
            return await deepseekService.reviewDocument(content, prompt, modelType);
        } 
        // 检查是否为建行方舟模型ID
        else if (modelType.includes('Deeseek-R1') || modelType.includes('DeepSeek-R1')) {
            logger.info(`使用建行方舟模型API进行审核: ${modelType}`);
            return await ccbfzService.reviewDocument(content, prompt, modelType);
        }
        // 其他模型返回模拟响应 
        else {
            logger.info(`使用模拟响应模式: ${modelType}`);
            await new Promise(resolve => setTimeout(resolve, 500 + Math.random() * 2000));
            return {
                result: `对"${prompt.substring(0, 30)}..."的审核结果: 符合要求。`,
                thinking: `分析过程：根据输入提示"${prompt.substring(0, 30)}..."，检查了相关内容，结果符合要求。`
            };
        }
    } catch (error) {
        logger.error(`API调用失败: ${error.message}`);
        logger.error(error.stack);
        console.error('API调用失败:', error);
        throw new Error(`API调用失败: ${error.message}`);
    }
}

// 直接使用 Node.js 调用 DeepSeek API
async function callDeepseekAPI(prompt, content) {
    try {
        logger.info('使用Node.js直接调用DeepSeek API...');
        console.log('使用Node.js直接调用DeepSeek API...');
        
        // 使用我们的 DeepseekService 进行文档审核
        const result = await deepseekService.reviewDocument(content, prompt);
        
        logger.info('DeepSeek API调用成功');
        
        return {
            answer: result.result,
            thinking: result.thinking || ''
        };
    } catch (error) {
        logger.error(`调用DeepSeek API时发生错误: ${error.message}`);
        
        // 如果API调用失败，返回一个模拟响应，而不是抛出错误
        console.warn('API调用失败，返回模拟响应');
        return {
            answer: `【API调用失败】无法连接到DeepSeek API(${error.message})。请检查：\n1. API密钥是否正确配置\n2. 网络连接是否正常\n3. .env中的DEEPSEEK_API_KEY和DEEPSEEK_API_URL配置是否正确`,
            thinking: `尝试调用DeepSeek API失败，错误信息: ${error.message}`
        };
    }
}

// 流式聊天API接口
app.post('/api/chat-stream', async (req, res) => {
    try {
        const { model, messages, temperature = 0.7, max_tokens = 2048 } = req.body;
        
        if (!messages || !Array.isArray(messages) || messages.length === 0) {
            return res.status(400).json({ error: '消息格式不正确' });
        }
        
        // 设置响应头，支持流式输出
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        res.setHeader('Transfer-Encoding', 'chunked');
        res.setHeader('Connection', 'keep-alive');
        res.setHeader('Cache-Control', 'no-cache');
        
        // 获取API配置信息
        let apiKey, apiUrl;
        if (model === 'deepseek') {
            apiKey = process.env.DEEPSEEK_API_KEY;
            apiUrl = process.env.DEEPSEEK_API_URL || 'https://api.deepseek.com/v1/reasoner/completions';
            console.log('使用Deepseek模型进行聊天');
        } else { // qwen
            apiKey = process.env.QWEN_API_KEY;
            apiUrl = process.env.QWEN_API_URL || 'https://api.qwen.ai/v1/chat/completions';
            console.log('使用Qwen模型进行聊天');
        }
        
        // 检查API密钥是否配置
        if (!apiKey || apiKey === 'your_deepseek_key_here' || apiKey === 'your_qwen_key_here') {
            console.warn(`警告: ${model}模型API密钥未正确配置，使用模拟响应流`); 
            // 模拟流式响应
            simulateStreamResponse(res, messages[messages.length - 1].content);
            return;
        }

        // 实际的API调用
        try {
            const response = await axios.post(apiUrl, {
                model: model === 'deepseek' ? 'deepseek-reasoner' : 'qwen-2.5',
                messages: messages,
                stream: true,
                temperature: temperature,
                max_tokens: max_tokens
            }, {
                headers: {
                    'Authorization': `Bearer ${apiKey}`,
                    'Content-Type': 'application/json'
                },
                responseType: 'stream'
            });
            
            // 将API响应流转发到客户端
            response.data.pipe(res);
            
            // 处理完成时关闭连接
            response.data.on('end', () => {
                console.log('流式响应完成');
                res.end();
            });
            
        } catch (error) {
            console.error('API调用失败:', error.message);
            // 如果API调用失败，回退到模拟响应
            simulateStreamResponse(res, messages[messages.length - 1].content);
        }
    } catch (error) {
        console.error('处理聊天请求失败:', error);
        res.status(500).json({ error: '服务器处理请求失败' });
    }
});

// 模拟流式响应的函数
function simulateStreamResponse(res, userMessage) {
    console.log('API调用失败，使用模拟流式响应');
    logger.warn('API调用失败，使用模拟流式响应');
    
    // 根据用户输入生成一个简单的响应
    const responseText = "API调用失败，请检查API密钥配置和网络连接。您可以在.env文件中设置正确的API密钥。" + 
                         "目前使用模拟响应代替。\n\n" + 
                         "问题可能原因：\n" + 
                         "1. API密钥未设置或不正确\n" + 
                         "2. 网络连接问题\n" + 
                         "3. API服务不可用\n\n" + 
                         "请联系管理员解决此问题。";
    
    // 将响应文本拆分为字符
    const chars = responseText.split('');
    
    // 模拟流式输出，每50毫秒发送一个字符
    let index = 0;
    const interval = setInterval(() => {
        if (index < chars.length) {
            // 发送单个字符
            res.write(chars[index]);
            index++;
        } else {
            // 发送完成，清除定时器并结束响应
            clearInterval(interval);
            res.end();
        }
    }, 50);
}

// 下载Excel文件
app.get('/download-excel/:filename', (req, res) => {
    const filename = req.params.filename;
    const filepath = path.join('uploads', filename);
    
    logger.info(`请求下载Excel文件: ${filename}`);
    
    if (!fs.existsSync(filepath)) {
        logger.warn(`Excel文件不存在: ${filepath}`);
        return res.status(404).send('文件不存在或已过期');
    }
    
    try {
        logger.info(`开始下载Excel文件: ${filename}`);
        res.download(filepath, filename, (err) => {
            if (err) {
                logger.error(`下载Excel文件失败: ${err.message}`);
                return res.status(500).send('下载失败');
            }
            
            // 下载完成后删除文件（可选）
            // fs.unlinkSync(filepath);
        });
    } catch (error) {
        logger.error(`Excel文件下载异常: ${error.message}`);
        res.status(500).send('服务器错误');
    }
});

// 下载Markdown文件
app.get('/download/:filename', (req, res) => {
    const filename = req.params.filename;
    const filepath = path.join('uploads', filename);
    
    logger.info(`请求下载文件: ${filename}`);
    
    if (!fs.existsSync(filepath)) {
        logger.warn(`文件不存在: ${filepath}`);
        return res.status(404).send('文件不存在或已过期');
    }
    
    try {
        logger.info(`开始下载文件: ${filename}`);
        res.download(filepath, filename, (err) => {
            if (err) {
                logger.error(`下载文件失败: ${err.message}`);
                return res.status(500).send('下载失败');
            }
            
            // 下载完成后删除文件（可选）
            // fs.unlinkSync(filepath);
        });
    } catch (error) {
        logger.error(`文件下载异常: ${error.message}`);
        res.status(500).send('服务器错误');
    }
});

// 添加新的直接调用路由
app.post('/api/review', async (req, res) => {
    try {
        const { content, prompt_template } = req.body;
        
        if (!content) {
            return res.status(400).json({
                error: '请求参数无效：缺少 content'
            });
        }
        
        // 调用 DeepSeek API 进行文档审核
        const result = await deepseekService.reviewDocument(content, prompt_template);
        
        // 返回审核结果
        res.json({
            result: result.result,
            thinking: result.thinking
        });
        
    } catch (error) {
        console.error('处理审核请求失败:', error);
        res.status(500).json({
            error: `处理审核请求失败: ${error.message}`
        });
    }
});

// 处理Excel生成Prompt
app.post('/process-excel', async (req, res) => {
    try {
        const { tempPath, filename } = req.body;
        
        if (!tempPath || !filename || !fs.existsSync(tempPath)) {
            return res.status(400).json({ error: '文件不存在或已过期，请重新上传' });
        }
        
        // 读取Excel文件
        const workbook = xlsx.readFile(tempPath);
        
        // 获取第一个未隐藏的工作表
        const sheetName = getFirstVisibleSheet(workbook);
        
        // 检查工作表是否存在
        if (!workbook.SheetNames.includes(sheetName)) {
            return res.status(400).json({ error: `Excel文件中未找到工作表"${sheetName}"` });
        }
        
        // 读取工作表数据
        const worksheet = workbook.Sheets[sheetName];
        const data = xlsx.utils.sheet_to_json(worksheet);
        
        // 为每行生成prompt
        for (let i = 0; i < data.length; i++) {
            const row = data[i];
            const category = row['审查检查类别'] || '';
            const item = row['审查检查项'] || '';
            
            if (!category || !item) continue;
            
            // 构建prompt模板
            const prompt = `##角色:你是一名软件技术方案与详细设计审核专家。
##任务：
根据待审核内容与具体检查项进行审核并给出审核结论。

##关键信息定义:
1、${category}相关内容：${item.substring(0, 50)}...

##要求:
检查结论要求:先给出整体结果为通过还是不通过，再逐一列出不符合检查项要求的项目，并逐一给出修改意见。
检查项如下:
1、仅审核"${category}"章节
2、${item}
若不涉及${category}相关内容则结论为不涉及。

##输出要求：
结论：当检查项均不存在输出不涉及，检查项存在且满足检查项要求时，输出通过，否则不通过
原因：输出不满足的事项及原文描述。格式一般为原文提及"xxx",但xxxxx，违反了【xxx】。满足或不涉及时，原因写无。

##输出示例1:
结论：不通过
原因:原文提及"循环插入数据"但未在后文提及记录行数的相关操作,违反了【一张表插入超过50条,需在插入前count(*)记录行数,插入后count(*)记录行数】的要求
##输出示例2:
结论:通过。
原因:无`;
            
            // 将prompt添加到数据中
            data[i].prompt = prompt;
        }
        
        // 将更新后的数据写回工作表
        const newWorkbook = xlsx.utils.book_new();
        const newWorksheet = xlsx.utils.json_to_sheet(data);
        xlsx.utils.book_append_sheet(newWorkbook, newWorksheet, sheetName);
        
        // 保存到新文件 - 使用英文名称避免乱码问题
        const timestamp = new Date().getTime();
        const outputFilename = `excel_prompts_${timestamp}.xlsx`;
        const outputPath = path.join('uploads', outputFilename);
        xlsx.writeFile(newWorkbook, outputPath);
        
        // 返回下载链接
        res.json({
            success: true,
            message: `成功为${data.length}行生成prompt`,
            download_path: '/download-excel/' + outputFilename
        });
    } catch (error) {
        res.status(500).json({ error: '处理Excel文件失败：' + error.message });
    }
});
// 服务器端口
const PORT = process.env.PORT || 3001;

// 启动服务器
const server = app.listen(PORT,'0.0.0.0', () => {
    logger.info(`======= Web服务启动 =======`);
    logger.info(`服务器运行在 http://localhost:${PORT}`);
    logger.info(`日志保存在 ${path.join(__dirname, 'log')} 目录下`);
    console.log(`服务器运行在 http://localhost:${PORT}`);
});

// 处理服务器错误
server.on('error', (error) => {
    logger.error(`服务器错误: ${error.message}`);
    console.error('服务器错误:', error);
});

// 处理进程退出事件
process.on('SIGTERM', () => {
    logger.info('接收到SIGTERM信号，关闭服务器');
    server.close(() => {
        logger.info('服务器已关闭');
        process.exit(0);
    });
});

process.on('SIGINT', () => {
    logger.info('接收到SIGINT信号，关闭服务器');
    server.close(() => {
        logger.info('服务器已关闭');
        process.exit(0);
    });
});
